﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.DirectoryServices;

namespace Library
{
  /// <summary>
  /// プリンターを表すクラスです。
  /// </summary>
  [DataObject()]
  public sealed class PrintQueue : DomainObject
  {
    #region プライベートフィールド
    private readonly string _name, _server;
    #endregion

    #region インターナルコンストラクター
    /// <summary>
    /// <see cref="DirectoryEntry"/> を指定して <see cref="PrintQueue"/> クラスの新しいインスタンスを初期化します。
    /// </summary>
    /// <param name="entry"><see cref="DirectoryEntry"/>。</param>
    internal PrintQueue(DirectoryEntry entry)
      : base(entry)
    {
      _name = entry.Properties["printerName"].Value.ToString();
      _server = entry.Properties["serverName"].Value.ToString();
    }
    #endregion

    #region パブリックプロパティ
    /// <summary>
    /// カラーかどうかを取得または設定します。
    /// </summary>
    public bool Color
    {
      get
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        return Convert.ToBoolean(base.Entry.Properties["printColor"].Value);
      }
      set
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        base.Entry.Properties["printColor"].Value = value;
      }
    }

    /// <summary>
    /// 両面かどうかを取得または設定します。
    /// </summary>
    public bool Duplex
    {
      get
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        return Convert.ToBoolean(base.Entry.Properties["printDuplexSupported"].Value);
      }
      set
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        base.Entry.Properties["printDuplexSupported"].Value = value;
      }
    }

    /// <summary>
    /// 名前を取得します。
    /// </summary>
    public string FullName
    {
      get
      {
        return base.Name;
      }
    }

    /// <summary>
    /// 場所を取得または設定します。
    /// </summary>
    public string Location
    {
      get
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        return (string)base.Entry.Properties["location"].Value;
      }
      set
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        base.Entry.Properties["location"].Value = value;
      }
    }

    /// <summary>
    /// 最高解像度を取得または設定します。
    /// </summary>
    public int? MaxResolution
    {
      get
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        return (int?)base.Entry.Properties["printMaxResolutionSupported"].Value;
      }
      set
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        base.Entry.Properties["printMaxResolutionSupported"].Value = value;
      }
    }

    /// <summary>
    /// モデルを取得または設定します。
    /// </summary>
    public string Model
    {
      get
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        return (string)base.Entry.Properties["driverName"].Value;
      }
      set
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        base.Entry.Properties["driverName"].Value = value;
      }
    }

    /// <summary>
    /// プリンター名を取得します。
    /// </summary>
    public override string Name
    {
      get
      {
        return _name;
      }
    }

    /// <summary>
    /// サーバー名を取得します。
    /// </summary>
    public string ServerName
    {
      get
      {
        return _server;
      }
    }

    /// <summary>
    /// 印刷速度を取得または設定します。
    /// </summary>
    public int? Speed
    {
      get
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        return (int?)base.Entry.Properties["printPagesPerMinute"].Value;
      }
      set
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        base.Entry.Properties["printPagesPerMinute"].Value = value;
      }
    }

    /// <summary>
    /// ホチキス止めかどうかを取得または設定します。
    /// </summary>
    public bool Stapling
    {
      get
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        return Convert.ToBoolean(base.Entry.Properties["printStaplingSupported"].Value);
      }
      set
      {
        if (base.IsDisposed)
        {
          throw new ObjectDisposedException(this.GetType().Name);
        }
        base.Entry.Properties["printStaplingSupported"].Value = value;
      }
    }
    #endregion

    #region パブリックメソッド
    /// <summary>
    /// 指定した名前のプリンターを検索します。このメソッドはデータバインド用です。
    /// </summary>
    /// <param name="name">名前。</param>
    /// <returns>プリンター。</returns>
    [DataObjectMethod(DataObjectMethodType.Select)]
    public static PrintQueue FindByName(string name)
    {
      return (PrintQueue)DirectoryAccess.FindDirectoryObject(name, CategoryType.PrintQueue);
    }

    /// <summary>
    /// プリンターの一覧を取得します。このメソッドはデータバインド用です。
    /// </summary>
    /// <returns>プリンターの一覧。</returns>
    [DataObjectMethod(DataObjectMethodType.Select)]
    public static IList<PrintQueue> GetPrintQueues()
    {
      return DirectoryAccess.GetPrintQueues();  //プリンターを取得
    }
    #endregion
  }
}
